package com.cencat.framework.file.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cencat.common.exception.BusinessException;
import com.cencat.common.model.Result;
import com.cencat.framework.file.dto.FileUploadRequest;
import com.cencat.framework.file.entity.FileInfo;
import com.cencat.framework.file.entity.FileStorageConfig;
import com.cencat.framework.file.mapper.FileInfoMapper;
import com.cencat.framework.file.mapper.FileStorageConfigMapper;
import com.cencat.framework.file.service.FileStorageService;
import com.cencat.framework.file.vo.FileInfoVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 文件存储服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileStorageServiceImpl implements FileStorageService {
    
    private final FileInfoMapper fileInfoMapper;
    private final FileStorageConfigMapper storageConfigMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileInfoVO uploadFile(FileUploadRequest request) {
        try {
            // 验证文件
            validateFile(request.getFile());
            
            // 获取存储配置
            FileStorageConfig storageConfig = getStorageConfig(request.getStorageType());
            
            // 生成文件KEY
            String fileKey = generateFileKey(request.getFile().getOriginalFilename());
            
            // 保存文件到存储后端
            String storageUrl = saveFileToStorage(request.getFile(), fileKey, storageConfig);
            
            // 保存文件信息到数据库
            FileInfo fileInfo = buildFileInfo(request, fileKey, storageUrl, storageConfig);
            fileInfoMapper.insert(fileInfo);
            
            return convertToVO(fileInfo);
            
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            throw new BusinessException("文件上传失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<FileInfoVO> uploadFiles(List<FileUploadRequest> requests) {
        List<FileInfoVO> results = new ArrayList<>();
        for (FileUploadRequest request : requests) {
            try {
                FileInfoVO fileInfoVO = uploadFile(request);
                results.add(fileInfoVO);
            } catch (Exception e) {
                log.error("批量上传文件失败: {}", e.getMessage(), e);
                // 继续处理其他文件
            }
        }
        return results;
    }
    
    @Override
    public byte[] downloadFile(String fileKey) {
        FileInfo fileInfo = fileInfoMapper.selectByFileKey(fileKey);
        if (fileInfo == null) {
            throw new BusinessException("文件不存在");
        }
        
        if (fileInfo.getStatus() == 0) {
            throw new BusinessException("文件已被删除");
        }
        
        try {
            return readFileFromStorage(fileKey, fileInfo);
        } catch (Exception e) {
            log.error("文件下载失败: {}", e.getMessage(), e);
            throw new BusinessException("文件下载失败: " + e.getMessage());
        }
    }
    
    @Override
    public String getPreviewUrl(String fileKey) {
        FileInfo fileInfo = fileInfoMapper.selectByFileKey(fileKey);
        if (fileInfo == null) {
            throw new BusinessException("文件不存在");
        }
        
        // 根据文件类型生成预览URL
        return generatePreviewUrl(fileInfo);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteFile(String fileKey) {
        FileInfo fileInfo = fileInfoMapper.selectByFileKey(fileKey);
        if (fileInfo == null) {
            return true; // 文件不存在，视为删除成功
        }
        
        try {
            // 从存储后端删除文件
            deleteFileFromStorage(fileKey, fileInfo);
            
            // 更新数据库状态为删除
            fileInfo.setStatus(0);
            fileInfo.setUpdateTime(LocalDateTime.now());
            fileInfoMapper.updateById(fileInfo);
            
            return true;
        } catch (Exception e) {
            log.error("文件删除失败: {}", e.getMessage(), e);
            throw new BusinessException("文件删除失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean deleteFiles(List<String> fileKeys) {
        for (String fileKey : fileKeys) {
            try {
                deleteFile(fileKey);
            } catch (Exception e) {
                log.error("批量删除文件失败: {}", e.getMessage(), e);
                // 继续处理其他文件
            }
        }
        return true;
    }
    
    @Override
    public FileInfoVO getFileInfo(String fileKey) {
        FileInfo fileInfo = fileInfoMapper.selectByFileKey(fileKey);
        if (fileInfo == null) {
            throw new BusinessException("文件不存在");
        }
        return convertToVO(fileInfo);
    }
    
    @Override
    public boolean fileExists(String fileKey) {
        FileInfo fileInfo = fileInfoMapper.selectByFileKey(fileKey);
        return fileInfo != null && fileInfo.getStatus() == 1;
    }
    
    @Override
    public FileInfoVO copyFile(String sourceFileKey, String targetPath) {
        // TODO: 实现文件复制逻辑
        throw new BusinessException("功能开发中");
    }
    
    @Override
    public FileInfoVO moveFile(String sourceFileKey, String targetPath) {
        // TODO: 实现文件移动逻辑
        throw new BusinessException("功能开发中");
    }
    
    @Override
    public String generateUploadSignature(String fileName, long fileSize) {
        // TODO: 实现上传签名生成逻辑
        throw new BusinessException("功能开发中");
    }
    
    @Override
    public int cleanupTemporaryFiles() {
        return fileInfoMapper.deleteExpiredTemporaryFiles();
    }
    
    // 私有方法实现...
    private void validateFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new BusinessException("文件不能为空");
        }
        
        if (file.getSize() > 100 * 1024 * 1024) { // 100MB限制
            throw new BusinessException("文件大小不能超过100MB");
        }
    }
    
    private FileStorageConfig getStorageConfig(String storageType) {
        FileStorageConfig config = storageConfigMapper.selectByStorageType(storageType);
        if (config == null || config.getStatus() == 0) {
            throw new BusinessException("存储配置不存在或已禁用");
        }
        return config;
    }
    
    private String generateFileKey(String originalFilename) {
        String extension = "";
        if (StringUtils.hasText(originalFilename)) {
            int dotIndex = originalFilename.lastIndexOf(".");
            if (dotIndex > 0) {
                extension = originalFilename.substring(dotIndex);
            }
        }
        return UUID.randomUUID().toString().replace("-", "") + extension;
    }
    
    private String saveFileToStorage(MultipartFile file, String fileKey, FileStorageConfig config) {
        // TODO: 根据存储类型实现具体的文件保存逻辑
        // 这里先实现本地存储
        try {
            Path uploadPath = Paths.get("uploads", fileKey);
            Files.createDirectories(uploadPath.getParent());
            Files.write(uploadPath, file.getBytes());
            return uploadPath.toString();
        } catch (IOException e) {
            throw new BusinessException("文件保存失败: " + e.getMessage());
        }
    }
    
    private FileInfo buildFileInfo(FileUploadRequest request, String fileKey, String storageUrl, FileStorageConfig config) {
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileKey(fileKey);
        fileInfo.setFileName(request.getFile().getOriginalFilename());
        fileInfo.setFilePath(request.getStoragePath());
        fileInfo.setFileSize(request.getFile().getSize());
        fileInfo.setFileType(getFileType(request.getFile().getContentType()));
        fileInfo.setMimeType(request.getFile().getContentType());
        fileInfo.setFileExtension(getFileExtension(request.getFile().getOriginalFilename()));
        fileInfo.setStorageConfigId(config.getId());
        fileInfo.setStorageKey(fileKey);
        fileInfo.setStorageUrl(storageUrl);
        fileInfo.setBusinessModule(request.getBusinessModule());
        fileInfo.setBusinessId(request.getBusinessId());
        fileInfo.setAccessLevel(request.getAccessLevel());
        fileInfo.setTemporary(request.getIsTemporary());
        fileInfo.setStatus(1);
        fileInfo.setCreateTime(LocalDateTime.now());
        fileInfo.setUpdateTime(LocalDateTime.now());
        
        return fileInfo;
    }
    
    private String getFileType(String contentType) {
        if (contentType == null) return "unknown";
        if (contentType.startsWith("image/")) return "image";
        if (contentType.startsWith("video/")) return "video";
        if (contentType.startsWith("audio/")) return "audio";
        if (contentType.equals("application/pdf")) return "pdf";
        if (contentType.startsWith("text/")) return "text";
        return "other";
    }
    
    private String getFileExtension(String filename) {
        if (filename == null) return "";
        int dotIndex = filename.lastIndexOf(".");
        return dotIndex > 0 ? filename.substring(dotIndex + 1) : "";
    }
    
    private byte[] readFileFromStorage(String fileKey, FileInfo fileInfo) {
        // TODO: 根据存储类型实现具体的文件读取逻辑
        try {
            Path filePath = Paths.get(fileInfo.getStorageUrl());
            return Files.readAllBytes(filePath);
        } catch (IOException e) {
            throw new BusinessException("文件读取失败: " + e.getMessage());
        }
    }
    
    private void deleteFileFromStorage(String fileKey, FileInfo fileInfo) {
        // TODO: 根据存储类型实现具体的文件删除逻辑
        try {
            Path filePath = Paths.get(fileInfo.getStorageUrl());
            Files.deleteIfExists(filePath);
        } catch (IOException e) {
            log.warn("文件删除失败: {}", e.getMessage());
        }
    }
    
    private String generatePreviewUrl(FileInfo fileInfo) {
        // TODO: 根据文件类型生成预览URL
        return fileInfo.getStorageUrl();
    }
    
    private FileInfoVO convertToVO(FileInfo fileInfo) {
        FileInfoVO vo = new FileInfoVO();
        BeanUtils.copyProperties(fileInfo, vo);
        vo.setIsTemporary(fileInfo.getTemporary());
        return vo;
    }
}